﻿using NewsPortal.Modularity.Core;
using System;
using System.Collections.Generic;
using System.Linq;

namespace NewsPortal.Web.Infrastructure.Modularity
{
    public static class GlobalModuleCollection
    {
        private static Dictionary<string, IModule> _modules;
      
        /// <summary>
        /// Validates Collection
        /// </summary>
        /// <returns></returns>
        public static bool IsValid()
        {
            return !(_modules == null || _modules.Count <= 0);
        }

        /// <summary>
        /// returns the module having the spcified key.
        /// </summary>
        /// <param name="name">module name</param>
        /// <returns>the module it self</returns>
        public static IModule Get(string name)
        {
            if (!IsValid())
            {
                throw new InvalidOperationException("Module list is empty. Consider calling populating collection by calling Populate method");
            }
            return _modules[name];
        }

        /// <summary>
        /// Adds the a module to the modules collection.
        /// </summary>
        /// <param name="module">the module to be added</param>
        public static void Add(IModule module)
        {
            if (!IsValid() || _modules.Any(m => m.Key == module.Name))
            {
                throw new InvalidOperationException("There is already a module with this name in module collection");
            }
            _modules.Add(module.Name, module);
        }

        /// <summary>
        /// removes a specific module from the modules list.
        /// </summary>
        /// <param name="key">the module key witch is its name</param>
        public static void Remove(string key)
        {
            if (!IsValid() || _modules.Any(m => m.Key == key))
            {
                throw new InvalidOperationException("There is no module with this key");
            }

            _modules.Remove(key);
        }

        /// <summary>
        /// returns all modules that are currently available.
        /// </summary>
        /// <returns>Modules</returns>
        public static IEnumerable<IModule> All()
        {
            List<IModule> modules = new List<IModule>();
            _modules.ForEach(m => modules.Add(m.Value));
            return modules;
        }

        /// <summary>
        /// Populate module list using default ModuleFactory and the DirectoryModuleTypeProvider and default "~/Modules/" path
        /// </summary>
        /// <returns>List of all Modules currently available...</returns>
        public static Dictionary<string, IModule> Populate()
        {
            return Populate(new ModuleFactory(new DirectoryModuleTypeProvider("~/Modules/")));
        }

        /// <summary>
        /// Populate module list using specified moduleFactory
        /// </summary>
        /// <param name="moduleFactory">the module factory that is used to create modules</param>
        /// <returns>List of all Modules currently available...</returns>
        public static Dictionary<string, IModule> Populate(IModuleFactory moduleFactory)
        {
            _modules = new Dictionary<string, IModule>();
            moduleFactory.Get().ForEach(m => _modules.Add(m.Name, m));
            return _modules;
        }
    }
}